﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

public class UIManager : ModuleBase<UIManager>
{
    public Transform[] LayerTrans;//UI层级

    public List<ViewBase> ViewCache = new List<ViewBase>();//界面缓存
    public List<ViewBase> ViewQueue = new List<ViewBase>();//界面队列
    public List<ViewBase> TipQueue = new List<ViewBase>();//提示队列
    public List<UIItemBase> ItemCache = new List<UIItemBase>();

    public override void Init()
    {
        Framework.Instance.AddUpdate(this);

        Transform uiRoot = Config.Instance.MainUIRoot;
        LayerTrans = new Transform[uiRoot.childCount];
        for (int i = 0, len = LayerTrans.Length; i < len; i++)
            LayerTrans[i] = uiRoot.GetChild(i);
    }

    public override void Update(float dt)
    {
        //删除超出缓存时间的界面
        for (int i = ViewCache.Count - 1; i >= 0; i--)
        {
            ViewBase view = ViewCache[i];
            if (!view.isPersistent)
            {
                view.cacheTime -= dt;
                if (view.cacheTime <= 0)
                {
                    view.Dispose();
                    ViewCache.RemoveAt(i);
                }
            }
        }
    }

    #region 界面
    //打开界面
    public void OpenView(ViewDefine key, params object[] param)
    {
        ViewBase view = GetView(key, true);
        if (view != null)
        {
            if (view.isTip)
            {
                TipQueue.Add(view);
                view.Open(param);
            }
            else
            {   //隐藏上一个界面
                ViewBase lastView = FindLastView(true);
                if (lastView != null)
                    lastView.Hide();

                ViewQueue.Add(view);
                view.Open(param);
            }
        }
    }

    //查找最后的界面
    private ViewBase FindLastView(bool isShow)
    {
        ViewBase lastView = null;
        for (int i = ViewQueue.Count - 1; i >= 0; i--)
        {
            ViewBase view = ViewQueue[i];
            if (view.isShow == isShow)
            {
                lastView = view;
                break;
            }
        }
        return lastView;
    }

    //关闭界面
    public void CloseView(ViewDefine key)
    {
        ViewBase view = FindView(key, ViewQueue);
        if (view == null)
            view = FindView(key, TipQueue);
        if (view != null)
        {
            view.Close();
            ViewCache.Add(view);

            //显示上一个界面
            if (!view.isTip)
            {
                ViewBase lastView = FindLastView(false);
                if (lastView != null)
                    lastView.Show();
            }
        }
    }

    //查找界面
    public ViewBase FindView(ViewDefine key, List<ViewBase> views)
    {
        ViewBase view = null;
        for (int i = 0, len = views.Count; i < len; i++)
        {
            var v = views[i];
            if (v.mKey == key)
            {
                view = v;
                views.RemoveAt(i);
                break;
            }
        }
        return view;
    }

    //获取界面
    public ViewBase GetView(ViewDefine key, bool create = false)
    {
        ViewBase view = FindView(key, ViewCache);
        if (view == null)
        {
            UIMap map = ViewMapping.GetMap(key);
            view = Activator.CreateInstance(map.mType) as ViewBase;
            string path = map.mPath;
            if (Config.Instance.UseAssetBundle)
            {
                int index = path.LastIndexOf("/") + 1;
                string name = path.Substring(index, path.Length - index);
                LoadManager.Instance.LoadAssetFromBundle("ui/panel/" + path, name, typeof(GameObject), (data) =>
                {
                    GameObject go = Object.Instantiate(data as GameObject);
                    view.Init(key, go);
                }, false, true);
            }
            else
            {
                LoadManager.Instance.LoadAsset("ui/panel", path, "prefab", typeof(GameObject), (data) =>
                {
                    GameObject go = Object.Instantiate(data as GameObject);
                    view.Init(key, go);
                }, false);
            }
        }
        return view;
    }
    #endregion

    #region 组件
    public T CreateItem<T>(UIBase uiBase, ItemDefine key, RectTransform parent, params object[] param) where T : UIItemBase
    {
        T item = GetItem<T>(uiBase, key);
        item.Create(parent, param);
        return item;
    }

    public void DestoryItem(UIItemBase item)
    {
        item.Destory();
        ItemCache.Add(item);
    }

    public T GetItem<T>(UIBase uiBase, ItemDefine key) where T : UIItemBase
    {
        T item = FindItem<T>(key);
        if (item == null)
        {
            string keyStr = key.ToString();
            GameObject prefab = null;
            List<UIHierarchy.ItemInfo> externals = uiBase.mHierarchy.externals;
            for (int i = 0, len = externals.Count; i < len; i++)
            {
                if (externals[i].name == keyStr)
                {
                    prefab = externals[i].item as GameObject;
                    break;
                }
            }

            if (prefab != null)
            {
                UIMap map = ViewMapping.GetMap(key);
                item = Activator.CreateInstance(map.mType) as T;
                item.Init(key, Object.Instantiate(prefab));
            }
        }
        return item;
    }

    public T FindItem<T>(ItemDefine key) where T : UIItemBase
    {
        T item = null;
        for (int i = ItemCache.Count - 1; i >= 0; i--)
        {
            UIItemBase it = ItemCache[i];
            if (it.mKey == key)
            {
                item = it as T;
                ItemCache.RemoveAt(i);
                break;
            }
        }
        return item;
    }
    #endregion

    #region 通用
    public static Vector2 TransformToCanvasLocalPosition(Transform current)
    {
        Config config = Config.Instance;
        var screenPos = config.WorldCamera.WorldToScreenPoint(current.position);
        Vector2 localPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(config.MainUITran, screenPos, config.UICamera, out localPos);
        return localPos;
    }


    public static void ConvertUIPos(Transform target, RectTransform ui)
    {
        Vector2 pos = TransformToCanvasLocalPosition(target);
        ui.anchoredPosition = pos;
    }
    #endregion
}